package com.xxg.renrenproduct.dao;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.Indexes;
import com.xxg.renrencommon.domain.bean.CarryProductInfo;
import com.xxg.renrencommon.domain.filedenum.productenum.CarryProductStatusEnum;
import com.xxg.renrenproduct.domain.result.ShopInfoResult;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.where;

/**
 * 带货信息dao
 *
 * @author szj
 * @date 2021/11/29
 */
@Repository
public class CarryProductInfoDao {
    private final MongoTemplate mongoTemplate;

    public CarryProductInfoDao(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
        createCollection();
    }

    /**
     * 创建collection
     */
    private void createCollection() {
        String collectionName = "carryProductInfo";
        MongoCollection<Document> collection;
        if (!mongoTemplate.getCollectionNames().contains(collectionName)) {
            collection = mongoTemplate.createCollection(CarryProductInfo.class);
            createIndex(collection);
        }
    }

    /**
     * 创建索引
     *
     * @param collection 数据集
     */
    private void createIndex(MongoCollection<Document> collection) {
        IndexOptions indexOptions = new IndexOptions().unique(true);
        collection.createIndex(Indexes.ascending("userId"));
        collection.createIndex(Indexes.ascending("shopId"));
        collection.createIndex(Indexes.ascending("spuId"));
        collection.createIndex(Indexes.compoundIndex(Indexes.ascending("shopId"), Indexes.ascending("spuId")), indexOptions);
    }

    public CarryProductInfo findByShopIdAndSpuId(Integer shopId, Integer spuId) {
        Query query = new Query(where("shopId").is(shopId).and("spuId").is(spuId));
        return mongoTemplate.findOne(query, CarryProductInfo.class);
    }

    public void insert(CarryProductInfo carryProductInfo) {
        carryProductInfo.setCreateTime(new Date());
        carryProductInfo.setUpdateTime(new Date());
        mongoTemplate.insert(carryProductInfo);
    }

    /**
     * 分页查询我收到申请的店铺
     *
     * @param userId   登录id
     * @param status   状态列表
     * @param pageNo   页码
     * @param pageSize 每页大小
     * @return List<ShopInfoResult>
     */
    public List<ShopInfoResult> findByOriginUserIdAndStatus(Integer userId, List<Integer> status, Integer pageNo, Integer pageSize) {
        List<AggregationOperation> aggregationOperations = new ArrayList<>();
        aggregationOperations.add(match(where("originUserId").is(userId).and("status").in(status)));
        aggregationOperations.add(sort(Sort.by("createTime").descending()));
        aggregationOperations.add(group("shopId").first("shopId").as("id")
                .first("userId").as("userId")
                .first("createTime").as("latestTime"));
        aggregationOperations.add(skip((long) ((pageNo - 1) * pageSize)));
        aggregationOperations.add(limit(pageSize));
        Aggregation agg = newAggregation(aggregationOperations);
        AggregationResults<ShopInfoResult> aggregate = mongoTemplate.aggregate(agg, CarryProductInfo.class, ShopInfoResult.class);
        return aggregate.getMappedResults();
    }

    /**
     * 分页查询我发申请的店铺
     *
     * @param userId   登录id
     * @param status   状态列表
     * @param pageNo   页码
     * @param pageSize 每页大小
     * @return List<ShopInfoResult>
     */
    public List<ShopInfoResult> findByUserIdAndStatus(Integer userId, List<Integer> status, Integer pageNo, Integer pageSize) {
        List<AggregationOperation> aggregationOperations = new ArrayList<>();
        aggregationOperations.add(match(where("userId").is(userId).and("status").in(status)));
        aggregationOperations.add(sort(Sort.by("createTime").descending()));
        aggregationOperations.add(group("originShopId").first("originShopId").as("id")
                .first("originUserId").as("userId")
                .first("createTime").as("latestTime"));
        aggregationOperations.add(skip((long) ((pageNo - 1) * pageSize)));
        aggregationOperations.add(limit(pageSize));
        Aggregation agg = newAggregation(aggregationOperations);
        AggregationResults<ShopInfoResult> aggregate = mongoTemplate.aggregate(agg, CarryProductInfo.class, ShopInfoResult.class);
        return aggregate.getMappedResults();
    }

    /**
     * 根据状态查我收到的某个店铺申请
     * @param userId
     * @param status
     * @param shopId
     * @return
     */
    public List<CarryProductInfo> findByOriginUserIdAndStatusAndShopId(Integer userId, List<Integer> status, Integer shopId) {
        Query query = new Query(where("originUserId").is(userId).and("status").in(status).and("shopId").is(shopId));
        query.with(Sort.by("createTime").descending());
        return mongoTemplate.find(query, CarryProductInfo.class);
    }

    /**
     * 根据状态查我发到某个店铺的申请
     * @param userId
     * @param status
     * @param shopId
     * @return
     */
    public List<CarryProductInfo> findByUserIdAndStatusAndOriginShopId(Integer userId, List<Integer> status, Integer shopId) {
        Query query = new Query(where("userId").is(userId).and("status").in(status).and("originShopId").is(shopId));
        query.with(Sort.by("createTime").descending());
        return mongoTemplate.find(query, CarryProductInfo.class);
    }

    public void updateStatusById(String id, Integer shopId, Integer status, Integer newSpuId) {
        Query query = new Query(where("_id").is(id).and("shopId").is(shopId).and("status").is(CarryProductStatusEnum.READY_VERIFY.getValue()));
        Update update = new Update();
        update.set("status", status);
        update.set("carrySpuId", newSpuId);
        mongoTemplate.updateFirst(query, update, CarryProductInfo.class);
    }

    public void updateStatusByShopIdAndUserId(int userId, Integer shopId, Integer status) {
        Query query = new Query(where("originUserId").is(userId).and("shopId").is(shopId).and("status").is(CarryProductStatusEnum.READY_VERIFY.getValue()));
        Update update = new Update();
        update.set("status", status);
        mongoTemplate.updateMulti(query, update, CarryProductInfo.class);
    }

    public CarryProductInfo findById(String id) {
        Query query = new Query(where("_id").is(id));
        return mongoTemplate.findOne(query, CarryProductInfo.class);
    }

    /**
     * 根据状态分页查我收到的某个店铺申请
     * @return List<CarryProductInfo>
     */
    public List<CarryProductInfo> findPageByOriginUserIdAndStatusAndShopId(int userId, List<Integer> status, Integer shopId, Integer pageNo, Integer pageSize) {
        Query query = new Query(where("originUserId").is(userId).and("status").in(status).and("shopId").is(shopId));
        query.with(Sort.by("createTime").descending());
        query.skip((pageNo - 1) * pageSize);
        query.limit(pageSize);
        return mongoTemplate.find(query, CarryProductInfo.class);
    }

    /**
     * 根据状态分页查我发到某个店铺的申请
     * @return List<CarryProductInfo>
     */
    public List<CarryProductInfo> findPageByUserIdAndStatusAndOriginShopId(int userId, List<Integer> status, Integer shopId, Integer pageNo, Integer pageSize) {
        Query query = new Query(where("userId").is(userId).and("status").in(status).and("originShopId").is(shopId));
        query.with(Sort.by("createTime").descending());
        query.skip((pageNo - 1) * pageSize);
        query.limit(pageSize);
        return mongoTemplate.find(query, CarryProductInfo.class);
    }

    public CarryProductInfo findByCarrySpuId(Integer carrySpuId) {
        Query query = new Query(where("carrySpuId").is(carrySpuId));
        return mongoTemplate.findOne(query, CarryProductInfo.class);
    }

    public void removeById(String id) {
        Query query = new Query(where("_id").is(id));
        mongoTemplate.remove(query, CarryProductInfo.class);
    }
}
